1
|
|
|
/* global kirki */ |
2
|
|
|
/** |
3
|
|
|
* The majority of the code in this file |
4
|
|
|
* is derived from the wp-customize-posts plugin |
5
|
|
|
* and the work of @westonruter to whom I am very grateful. |
6
|
|
|
* |
7
|
|
|
* @see https://github.com/xwp/wp-customize-posts |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
( function() { |
11
|
|
|
'use strict'; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* A dynamic color-alpha control. |
15
|
|
|
* |
16
|
|
|
* @class |
17
|
|
|
* @augments wp.customize.Control |
18
|
|
|
* @augments wp.customize.Class |
19
|
|
|
*/ |
20
|
|
|
wp.customize.kirkiDynamicControl = wp.customize.Control.extend({ |
21
|
|
|
|
22
|
|
|
initialize: function( id, options ) { |
23
|
|
|
var control = this, |
|
|
|
|
24
|
|
|
args = options || {}; |
25
|
|
|
|
26
|
|
|
args.params = args.params || {}; |
27
|
|
|
if ( ! args.params.type ) { |
28
|
|
|
args.params.type = 'kirki-generic'; |
29
|
|
|
} |
30
|
|
|
if ( ! args.params.content ) { |
31
|
|
|
args.params.content = jQuery( '<li></li>' ); |
32
|
|
|
args.params.content.attr( 'id', 'customize-control-' + id.replace( /]/g, '' ).replace( /\[/g, '-' ) ); |
33
|
|
|
args.params.content.attr( 'class', 'customize-control customize-control-' + args.params.type ); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
control.propertyElements = []; |
37
|
|
|
wp.customize.Control.prototype.initialize.call( control, id, args ); |
38
|
|
|
}, |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Add bidirectional data binding links between inputs and the setting(s). |
42
|
|
|
* |
43
|
|
|
* This is copied from wp.customize.Control.prototype.initialize(). It |
44
|
|
|
* should be changed in Core to be applied once the control is embedded. |
45
|
|
|
* |
46
|
|
|
* @private |
47
|
|
|
* @returns {null} |
48
|
|
|
*/ |
49
|
|
|
_setUpSettingRootLinks: function() { |
50
|
|
|
var control = this, |
|
|
|
|
51
|
|
|
nodes = control.container.find( '[data-customize-setting-link]' ); |
52
|
|
|
|
53
|
|
|
nodes.each( function() { |
54
|
|
|
var node = jQuery( this ); |
|
|
|
|
55
|
|
|
|
56
|
|
|
wp.customize( node.data( 'customizeSettingLink' ), function( setting ) { |
57
|
|
|
var element = new wp.customize.Element( node ); |
|
|
|
|
58
|
|
|
control.elements.push( element ); |
59
|
|
|
element.sync( setting ); |
60
|
|
|
element.set( setting() ); |
61
|
|
|
}); |
62
|
|
|
}); |
63
|
|
|
}, |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Add bidirectional data binding links between inputs and the setting properties. |
67
|
|
|
* |
68
|
|
|
* @private |
69
|
|
|
* @returns {null} |
70
|
|
|
*/ |
71
|
|
|
_setUpSettingPropertyLinks: function() { |
72
|
|
|
var control = this, |
|
|
|
|
73
|
|
|
nodes; |
74
|
|
|
|
75
|
|
|
if ( ! control.setting ) { |
76
|
|
|
return; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
nodes = control.container.find( '[data-customize-setting-property-link]' ); |
80
|
|
|
|
81
|
|
|
nodes.each( function() { |
82
|
|
|
var node = jQuery( this ), |
|
|
|
|
83
|
|
|
element, |
84
|
|
|
propertyName = node.data( 'customizeSettingPropertyLink' ); |
85
|
|
|
|
86
|
|
|
element = new wp.customize.Element( node ); |
87
|
|
|
control.propertyElements.push( element ); |
88
|
|
|
element.set( control.setting()[ propertyName ] ); |
89
|
|
|
|
90
|
|
|
element.bind( function( newPropertyValue ) { |
91
|
|
|
var newSetting = control.setting(); |
|
|
|
|
92
|
|
|
if ( newPropertyValue === newSetting[ propertyName ] ) { |
93
|
|
|
return; |
94
|
|
|
} |
95
|
|
|
newSetting = _.clone( newSetting ); |
96
|
|
|
newSetting[ propertyName ] = newPropertyValue; |
97
|
|
|
control.setting.set( newSetting ); |
98
|
|
|
} ); |
99
|
|
|
control.setting.bind( function( newValue ) { |
100
|
|
|
if ( newValue[ propertyName ] !== element.get() ) { |
101
|
|
|
element.set( newValue[ propertyName ] ); |
102
|
|
|
} |
103
|
|
|
} ); |
104
|
|
|
}); |
105
|
|
|
}, |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @inheritdoc |
109
|
|
|
*/ |
110
|
|
|
ready: function() { |
111
|
|
|
var control = this; |
|
|
|
|
112
|
|
|
|
113
|
|
|
control._setUpSettingRootLinks(); |
114
|
|
|
control._setUpSettingPropertyLinks(); |
115
|
|
|
|
116
|
|
|
wp.customize.Control.prototype.ready.call( control ); |
117
|
|
|
|
118
|
|
|
control.deferred.embedded.done( function() { |
119
|
|
|
control.initKirkiControl( control ); |
120
|
|
|
}); |
121
|
|
|
}, |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Embed the control in the document. |
125
|
|
|
* |
126
|
|
|
* Override the embed() method to do nothing, |
127
|
|
|
* so that the control isn't embedded on load, |
128
|
|
|
* unless the containing section is already expanded. |
129
|
|
|
* |
130
|
|
|
* @returns {null} |
131
|
|
|
*/ |
132
|
|
|
embed: function() { |
133
|
|
|
var control = this, |
|
|
|
|
134
|
|
|
sectionId = control.section(); |
135
|
|
|
|
136
|
|
|
if ( ! sectionId ) { |
137
|
|
|
return; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
wp.customize.section( sectionId, function( section ) { |
141
|
|
|
if ( 'kirki-expanded' === section.params.type || section.expanded() || wp.customize.settings.autofocus.control === control.id ) { |
142
|
|
|
control.actuallyEmbed(); |
143
|
|
|
} else { |
144
|
|
|
section.expanded.bind( function( expanded ) { |
145
|
|
|
if ( expanded ) { |
146
|
|
|
control.actuallyEmbed(); |
147
|
|
|
} |
148
|
|
|
} ); |
149
|
|
|
} |
150
|
|
|
} ); |
151
|
|
|
}, |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Deferred embedding of control when actually |
155
|
|
|
* |
156
|
|
|
* This function is called in Section.onChangeExpanded() so the control |
157
|
|
|
* will only get embedded when the Section is first expanded. |
158
|
|
|
* |
159
|
|
|
* @returns {null} |
160
|
|
|
*/ |
161
|
|
|
actuallyEmbed: function() { |
162
|
|
|
var control = this; |
|
|
|
|
163
|
|
|
if ( 'resolved' === control.deferred.embedded.state() ) { |
164
|
|
|
return; |
165
|
|
|
} |
166
|
|
|
control.renderContent(); |
167
|
|
|
control.deferred.embedded.resolve(); // This triggers control.ready(). |
168
|
|
|
}, |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* This is not working with autofocus. |
172
|
|
|
* |
173
|
|
|
* @param {object} [args] Args. |
174
|
|
|
* @returns {null} |
175
|
|
|
*/ |
176
|
|
|
focus: function( args ) { |
177
|
|
|
var control = this; |
|
|
|
|
178
|
|
|
control.actuallyEmbed(); |
179
|
|
|
wp.customize.Control.prototype.focus.call( control, args ); |
180
|
|
|
}, |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Additional actions that run on ready. |
184
|
|
|
* |
185
|
|
|
* @param {object} [args] Args. |
|
|
|
|
186
|
|
|
* @returns {null} |
187
|
|
|
*/ |
188
|
|
|
initKirkiControl: function( control ) { |
189
|
|
|
if ( 'undefined' !== typeof kirki.control[ control.params.type ] ) { |
190
|
|
|
kirki.control[ control.params.type ].init( control ); |
191
|
|
|
return; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
// Save the value |
195
|
|
|
this.container.on( 'change keyup paste click', 'input', function() { |
196
|
|
|
control.setting.set( jQuery( this ).val() ); |
197
|
|
|
}); |
198
|
|
|
}, |
199
|
|
|
|
200
|
|
|
kirkiValidateCSSValue: function( value ) { |
201
|
|
|
|
202
|
|
|
var validUnits = ['rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax'], |
|
|
|
|
203
|
|
|
numericValue, |
204
|
|
|
unit; |
205
|
|
|
|
206
|
|
|
// 0 is always a valid value, and we can't check calc() values effectively. |
207
|
|
|
if ( '0' === value || ( 0 <= value.indexOf( 'calc(' ) && 0 <= value.indexOf( ')' ) ) ) { |
208
|
|
|
return true; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
if ( 'auto' === value || 'inherit' === value || 'initial' === value ) { |
212
|
|
|
return true; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
// Get the numeric value. |
216
|
|
|
numericValue = parseFloat( value ); |
217
|
|
|
|
218
|
|
|
// Get the unit |
219
|
|
|
unit = value.replace( numericValue, '' ); |
220
|
|
|
|
221
|
|
|
// Check the validity of the numeric value and units. |
222
|
|
|
if ( isNaN( numericValue ) || -1 === jQuery.inArray( unit, validUnits ) ) { |
223
|
|
|
return false; |
224
|
|
|
} |
225
|
|
|
return true; |
226
|
|
|
} |
227
|
|
|
}); |
228
|
|
|
})(); |
229
|
|
|
|
230
|
|
|
_.each( kirki.control, function( obj, type ) { |
231
|
|
|
wp.customize.controlConstructor[ type ] = wp.customize.kirkiDynamicControl.extend({}); |
232
|
|
|
} ); |
233
|
|
|
|
Since ECMAScript 6, you can create block-scoped vars or constants with the keywords
let
orconst
. These variables/constants are only valid in the code block where they have been declared.Consider the following two pieces of code:
and
The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.
To know more about this ECMA6 feature, look at the MDN pages on let and const.